Red/System [
	Title:	"Implementation of wcwidth() and wcswidth() for Unicode."
	Author: "Xie Qingtian"
	File: 	%wcwidth.reds
	Tabs: 	4
	Rights: "Copyright (C) 2014-2015 Xie Qingtian. All rights reserved."
	License: {
		Distributed under the Boost Software License, Version 1.0.
		See https://github.com/red/red/blob/master/BSL-License.txt
	}
	Notes: {
		This code was originally derived directly from C code of the same name, 
		whose latest version is available at: wcwidth.c by Markus Kuhn.
		See http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c

		+ Update to Unicode 15.0
	}
]
combining-table: [
	0300h 036Fh 0483h 0489h 0591h 05BDh
	05BFh 05BFh 05C1h 05C2h 05C4h 05C5h
	05C7h 05C7h 0600h 0605h 0610h 061Ah
	061Ch 061Ch 064Bh 065Fh 0670h 0670h
	06D6h 06DDh 06DFh 06E4h 06E7h 06E8h
	06EAh 06EDh 070Fh 070Fh 0711h 0711h
	0730h 074Ah 07A6h 07B0h 07EBh 07F3h
	07FDh 07FDh 0816h 0819h 081Bh 0823h
	0825h 0827h 0829h 082Dh 0859h 085Bh
	0898h 089Fh 08CAh 08E1h 08E3h 0902h
	093Ah 093Ah 093Ch 093Ch 0941h 0948h
	094Dh 094Dh 0951h 0957h 0962h 0963h
	0981h 0981h 09BCh 09BCh 09C1h 09C4h
	09CDh 09CDh 09E2h 09E3h 09FEh 09FEh
	0A01h 0A02h 0A3Ch 0A3Ch 0A41h 0A42h
	0A47h 0A48h 0A4Bh 0A4Dh 0A51h 0A51h
	0A70h 0A71h 0A75h 0A75h 0A81h 0A82h
	0ABCh 0ABCh 0AC1h 0AC5h 0AC7h 0AC8h
	0ACDh 0ACDh 0AE2h 0AE3h 0AFAh 0AFFh
	0B01h 0B01h 0B3Ch 0B3Ch 0B3Fh 0B3Fh
	0B41h 0B44h 0B4Dh 0B4Dh 0B55h 0B56h
	0B62h 0B63h 0B82h 0B82h 0BC0h 0BC0h
	0BCDh 0BCDh 0C00h 0C00h 0C04h 0C04h
	0C3Ch 0C3Ch 0C3Eh 0C40h 0C46h 0C48h
	0C4Ah 0C4Dh 0C55h 0C56h 0C62h 0C63h
	0C81h 0C81h 0CBCh 0CBCh 0CBFh 0CBFh
	0CC6h 0CC6h 0CCCh 0CCDh 0CE2h 0CE3h
	0D00h 0D01h 0D3Bh 0D3Ch 0D41h 0D44h
	0D4Dh 0D4Dh 0D62h 0D63h 0D81h 0D81h
	0DCAh 0DCAh 0DD2h 0DD4h 0DD6h 0DD6h
	0E31h 0E31h 0E34h 0E3Ah 0E47h 0E4Eh
	0EB1h 0EB1h 0EB4h 0EBCh 0EC8h 0ECDh
	0F18h 0F19h 0F35h 0F35h 0F37h 0F37h
	0F39h 0F39h 0F71h 0F7Eh 0F80h 0F84h
	0F86h 0F87h 0F8Dh 0F97h 0F99h 0FBCh
	0FC6h 0FC6h 102Dh 1030h 1032h 1037h
	1039h 103Ah 103Dh 103Eh 1058h 1059h
	105Eh 1060h 1071h 1074h 1082h 1082h
	1085h 1086h 108Dh 108Dh 109Dh 109Dh
	1160h 11FFh 135Dh 135Fh 1712h 1714h
	1732h 1733h 1752h 1753h 1772h 1773h
	17B4h 17B5h 17B7h 17BDh 17C6h 17C6h
	17C9h 17D3h 17DDh 17DDh 180Bh 180Dh
	180Fh 180Fh 1885h 1886h 18A9h 18A9h
	1920h 1922h 1927h 1928h 1932h 1932h
	1939h 193Bh 1A17h 1A18h 1A1Bh 1A1Bh
	1A56h 1A56h 1A58h 1A5Eh 1A60h 1A60h
	1A62h 1A62h 1A65h 1A6Ch 1A73h 1A7Ch
	1A7Fh 1A7Fh 1AB0h 1ACEh 1B00h 1B03h
	1B34h 1B34h 1B36h 1B3Ah 1B3Ch 1B3Ch
	1B42h 1B42h 1B6Bh 1B73h 1B80h 1B81h
	1BA2h 1BA5h 1BA8h 1BA9h 1BABh 1BADh
	1BE6h 1BE6h 1BE8h 1BE9h 1BEDh 1BEDh
	1BEFh 1BF1h 1C2Ch 1C33h 1C36h 1C37h
	1CD0h 1CD2h 1CD4h 1CE0h 1CE2h 1CE8h
	1CEDh 1CEDh 1CF4h 1CF4h 1CF8h 1CF9h
	1DC0h 1DFFh 20D0h 20F0h 2CEFh 2CF1h
	2D7Fh 2D7Fh 2DE0h 2DFFh 302Ah 302Dh
	3099h 309Ah A66Fh A672h A674h A67Dh
	A69Eh A69Fh A6F0h A6F1h A802h A802h
	A806h A806h A80Bh A80Bh A825h A826h
	A82Ch A82Ch A8C4h A8C5h A8E0h A8F1h
	A8FFh A8FFh A926h A92Dh A947h A951h
	A980h A982h A9B3h A9B3h A9B6h A9B9h
	A9BCh A9BDh A9E5h A9E5h AA29h AA2Eh
	AA31h AA32h AA35h AA36h AA43h AA43h
	AA4Ch AA4Ch AA7Ch AA7Ch AAB0h AAB0h
	AAB2h AAB4h AAB7h AAB8h AABEh AABFh
	AAC1h AAC1h AAECh AAEDh AAF6h AAF6h
	ABE5h ABE5h ABE8h ABE8h ABEDh ABEDh
	D7B0h D7C6h D7CBh D7FBh FB1Eh FB1Eh
	FE00h FE0Fh FE20h FE2Fh 000101FDh 000101FDh
	000102E0h 000102E0h 00010376h 0001037Ah 00010A01h 00010A03h
	00010A05h 00010A06h 00010A0Ch 00010A0Fh 00010A38h 00010A3Ah
	00010A3Fh 00010A3Fh 00010AE5h 00010AE6h 00010D24h 00010D27h
	00010EABh 00010EACh 00010F46h 00010F50h 00010F82h 00010F85h
	00011001h 00011001h 00011038h 00011046h 00011070h 00011070h
	00011073h 00011074h 0001107Fh 00011081h 000110B3h 000110B6h
	000110B9h 000110BAh 000110C2h 000110C2h 00011100h 00011102h
	00011127h 0001112Bh 0001112Dh 00011134h 00011173h 00011173h
	00011180h 00011181h 000111B6h 000111BEh 000111C9h 000111CCh
	000111CFh 000111CFh 0001122Fh 00011231h 00011234h 00011234h
	00011236h 00011237h 0001123Eh 0001123Eh 000112DFh 000112DFh
	000112E3h 000112EAh 00011300h 00011301h 0001133Bh 0001133Ch
	00011340h 00011340h 00011366h 0001136Ch 00011370h 00011374h
	00011438h 0001143Fh 00011442h 00011444h 00011446h 00011446h
	0001145Eh 0001145Eh 000114B3h 000114B8h 000114BAh 000114BAh
	000114BFh 000114C0h 000114C2h 000114C3h 000115B2h 000115B5h
	000115BCh 000115BDh 000115BFh 000115C0h 000115DCh 000115DDh
	00011633h 0001163Ah 0001163Dh 0001163Dh 0001163Fh 00011640h
	000116ABh 000116ABh 000116ADh 000116ADh 000116B0h 000116B5h
	000116B7h 000116B7h 0001171Dh 0001171Fh 00011722h 00011725h
	00011727h 0001172Bh 0001182Fh 00011837h 00011839h 0001183Ah
	0001193Bh 0001193Ch 0001193Eh 0001193Eh 00011943h 00011943h
	000119D4h 000119D7h 000119DAh 000119DBh 000119E0h 000119E0h
	00011A01h 00011A0Ah 00011A33h 00011A38h 00011A3Bh 00011A3Eh
	00011A47h 00011A47h 00011A51h 00011A56h 00011A59h 00011A5Bh
	00011A8Ah 00011A96h 00011A98h 00011A99h 00011C30h 00011C36h
	00011C38h 00011C3Dh 00011C3Fh 00011C3Fh 00011C92h 00011CA7h
	00011CAAh 00011CB0h 00011CB2h 00011CB3h 00011CB5h 00011CB6h
	00011D31h 00011D36h 00011D3Ah 00011D3Ah 00011D3Ch 00011D3Dh
	00011D3Fh 00011D45h 00011D47h 00011D47h 00011D90h 00011D91h
	00011D95h 00011D95h 00011D97h 00011D97h 00011EF3h 00011EF4h
	00016AF0h 00016AF4h 00016B30h 00016B36h 00016F4Fh 00016F4Fh
	00016F8Fh 00016F92h 00016FE4h 00016FE4h 0001BC9Dh 0001BC9Eh
	0001CF00h 0001CF2Dh 0001CF30h 0001CF46h 0001D167h 0001D169h
	0001D17Bh 0001D182h 0001D185h 0001D18Bh 0001D1AAh 0001D1ADh
	0001D242h 0001D244h 0001DA00h 0001DA36h 0001DA3Bh 0001DA6Ch
	0001DA75h 0001DA75h 0001DA84h 0001DA84h 0001DA9Bh 0001DA9Fh
	0001DAA1h 0001DAAFh 0001E000h 0001E006h 0001E008h 0001E018h
	0001E01Bh 0001E021h 0001E023h 0001E024h 0001E026h 0001E02Ah
	0001E130h 0001E136h 0001E2AEh 0001E2AEh 0001E2ECh 0001E2EFh
	0001E8D0h 0001E8D6h 0001E944h 0001E94Ah 000E0100h 000E01EFh
]

double-width-table: [
	1100h 115Fh 231Ah 231Bh 2329h 232Ah
	23E9h 23ECh 23F0h 23F0h 23F3h 23F3h
	25FDh 25FEh 2614h 2615h 2648h 2653h
	267Fh 267Fh 2693h 2693h 26A1h 26A1h
	26AAh 26ABh 26BDh 26BEh 26C4h 26C5h
	26CEh 26CEh 26D4h 26D4h 26EAh 26EAh
	26F2h 26F3h 26F5h 26F5h 26FAh 26FAh
	26FDh 26FDh 2705h 2705h 270Ah 270Bh
	2728h 2728h 274Ch 274Ch 274Eh 274Eh
	2753h 2755h 2757h 2757h 2795h 2797h
	27B0h 27B0h 27BFh 27BFh 2B1Bh 2B1Ch
	2B50h 2B50h 2B55h 2B55h 2E80h 2E99h
	2E9Bh 2EF3h 2F00h 2FD5h 2FF0h 2FFBh
	3000h 3029h 302Eh 303Eh 3041h 3096h
	309Bh 30FFh 3105h 312Fh 3131h 318Eh
	3190h 31E3h 31F0h 321Eh 3220h 3247h
	3250h 4DBFh 4E00h A48Ch A490h A4C6h
	A960h A97Ch AC00h D7A3h F900h FAFFh
	FE10h FE19h FE30h FE52h FE54h FE66h
	FE68h FE6Bh FF01h FF60h FFE0h FFE6h
	00016FE0h 00016FE3h 00016FF0h 00016FF1h 00017000h 000187F7h
	00018800h 00018CD5h 00018D00h 00018D08h 0001AFF0h 0001AFF3h
	0001AFF5h 0001AFFBh 0001AFFDh 0001AFFEh 0001B000h 0001B122h
	0001B150h 0001B152h 0001B164h 0001B167h 0001B170h 0001B2FBh
	0001F004h 0001F004h 0001F0CFh 0001F0CFh 0001F18Eh 0001F18Eh
	0001F191h 0001F19Ah 0001F200h 0001F202h 0001F210h 0001F23Bh
	0001F240h 0001F248h 0001F250h 0001F251h 0001F260h 0001F265h
	0001F300h 0001F320h 0001F32Dh 0001F335h 0001F337h 0001F37Ch
	0001F37Eh 0001F393h 0001F3A0h 0001F3CAh 0001F3CFh 0001F3D3h
	0001F3E0h 0001F3F0h 0001F3F4h 0001F3F4h 0001F3F8h 0001F43Eh
	0001F440h 0001F440h 0001F442h 0001F4FCh 0001F4FFh 0001F53Dh
	0001F54Bh 0001F54Eh 0001F550h 0001F567h 0001F57Ah 0001F57Ah
	0001F595h 0001F596h 0001F5A4h 0001F5A4h 0001F5FBh 0001F64Fh
	0001F680h 0001F6C5h 0001F6CCh 0001F6CCh 0001F6D0h 0001F6D2h
	0001F6D5h 0001F6D7h 0001F6DDh 0001F6DFh 0001F6EBh 0001F6ECh
	0001F6F4h 0001F6FCh 0001F7E0h 0001F7EBh 0001F7F0h 0001F7F0h
	0001F90Ch 0001F93Ah 0001F93Ch 0001F945h 0001F947h 0001F9FFh
	0001FA70h 0001FA74h 0001FA78h 0001FA7Ch 0001FA80h 0001FA86h
	0001FA90h 0001FAACh 0001FAB0h 0001FABAh 0001FAC0h 0001FAC5h
	0001FAD0h 0001FAD9h 0001FAE0h 0001FAE7h 0001FAF0h 0001FAF6h
	00020000h 0002FFFDh 00030000h 0003FFFDh
]

in-table?: func [
	cp		[integer!]
	table	[int-ptr!]
	max		[integer!]
	return: [logic!]
	/local
		a	[integer!]
		b	[integer!]
][
	if any [cp < table/1 cp > table/max][return no]

	a: -1
	until [
		a: a + 2
		b: a + 1
		if all [cp >= table/a cp <= table/b][return yes]
		b = max
	]
	no
]

wcwidth?: func [
	cp		[integer!]
	return: [integer!]
][
	if zero? cp [return 0]
	if any [						;-- tests for 8-bit control characters
		cp < 32
		all [cp >= 7Fh cp < A0h]
	][return 1]

	if in-table? cp combining-table size? combining-table [return 0]
	if in-table? cp double-width-table size? double-width-table [return 2]
	1
]

#if OS = 'Windows [
	ambiguous-table: [
		00A1h 00A1h 00A4h 00A4h 00A7h 00A8h
		00AAh 00AAh 00AEh 00AEh 00B0h 00B4h
		00B6h 00BAh 00BCh 00BFh 00C6h 00C6h
		00D0h 00D0h 00D7h 00D8h 00DEh 00E1h
		00E6h 00E6h 00E8h 00EAh 00ECh 00EDh
		00F0h 00F0h 00F2h 00F3h 00F7h 00FAh
		00FCh 00FCh 00FEh 00FEh 0101h 0101h
		0111h 0111h 0113h 0113h 011Bh 011Bh
		0126h 0127h 012Bh 012Bh 0131h 0133h
		0138h 0138h 013Fh 0142h 0144h 0144h
		0148h 014Bh 014Dh 014Dh 0152h 0153h
		0166h 0167h 016Bh 016Bh 01CEh 01CEh
		01D0h 01D0h 01D2h 01D2h 01D4h 01D4h
		01D6h 01D6h 01D8h 01D8h 01DAh 01DAh
		01DCh 01DCh 0251h 0251h 0261h 0261h
		02C4h 02C4h 02C7h 02C7h 02C9h 02CBh
		02CDh 02CDh 02D0h 02D0h 02D8h 02DBh
		02DDh 02DDh 02DFh 02DFh 0391h 03A1h
		03A3h 03A9h 03B1h 03C1h 03C3h 03C9h
		0401h 0401h 0410h 044Fh 0451h 0451h
		2010h 2010h 2013h 2016h 2018h 2019h
		201Ch 201Dh 2020h 2022h 2024h 2027h
		2030h 2030h 2032h 2033h 2035h 2035h
		203Bh 203Bh 203Eh 203Eh 2074h 2074h
		207Fh 207Fh 2081h 2084h 20ACh 20ACh
		2103h 2103h 2105h 2105h 2109h 2109h
		2113h 2113h 2116h 2116h 2121h 2122h
		2126h 2126h 212Bh 212Bh 2153h 2154h
		215Bh 215Eh 2160h 216Bh 2170h 2179h
		2190h 2199h 21B8h 21B9h 21D2h 21D2h
		21D4h 21D4h 21E7h 21E7h 2200h 2200h
		2202h 2203h 2207h 2208h 220Bh 220Bh
		220Fh 220Fh 2211h 2211h 2215h 2215h
		221Ah 221Ah 221Dh 2220h 2223h 2223h
		2225h 2225h 2227h 222Ch 222Eh 222Eh
		2234h 2237h 223Ch 223Dh 2248h 2248h
		224Ch 224Ch 2252h 2252h 2260h 2261h
		2264h 2267h 226Ah 226Bh 226Eh 226Fh
		2282h 2283h 2286h 2287h 2295h 2295h
		2299h 2299h 22A5h 22A5h 22BFh 22BFh
		2312h 2312h 2460h 24E9h 24EBh 254Bh
		2550h 2573h 2580h 258Fh 2592h 2595h
		25A0h 25A1h 25A3h 25A9h 25B2h 25B3h
		25B6h 25B7h 25BCh 25BDh 25C0h 25C1h
		25C6h 25C8h 25CBh 25CBh 25CEh 25D1h
		25E2h 25E5h 25EFh 25EFh 2605h 2606h
		2609h 2609h 260Eh 260Fh 2614h 2615h
		261Ch 261Ch 261Eh 261Eh 2640h 2640h
		2642h 2642h 2660h 2661h 2663h 2665h
		2667h 266Ah 266Ch 266Dh 266Fh 266Fh
		273Dh 273Dh 2776h 277Fh E000h F8FFh
		FFFDh FFFDh 000F0000h 000FFFFDh 00100000h 0010FFFDh
	]

	cjk-wcwidth?: func [
		cp		[integer!]
		return: [integer!]
	][
		if in-table? cp ambiguous-table size? ambiguous-table [return 2]
		wcwidth? cp
	]
]
